﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mbr.Reviews.Core;
using Mbr.Reviews.Core.Exceptions;
using Moq;
using Mbr.Reviews.Core.Contracts;

namespace Mbr.Reviews.Core.Tests
{
    [TestClass]
    public class WhenSearchIsPerformed
    {
        private string keywordForNoResults = "sdfgdflgh3457usghiuhviuasdfgs7dg";
        private string keywordForSomeResults = "samsung";

        [TestMethod]
        [ExpectedException(typeof(NoKeywordsException))]
        public void ThenAtLeastOneKeywordShouldBeProvided()
        {
            var whiteSpaces = new string[] { " ", "\t", "\r", "\n", " \t\r\n" };
            var productFinder = new ProductFinder();

            productFinder.Find(null);
            productFinder.Find(string.Empty);
            productFinder.Find(whiteSpaces);
        }

        [TestMethod]
        public void ThenZeroOrMoreProductsShouldBeReturned()
        {
            var productFinder = new ProductFinder();
            var foundProducts = productFinder.Find("test");

            Assert.IsTrue(foundProducts.Count() >= 0);
        }

        [TestMethod]
        public void IfSomeProductMatchesAnyKeywordItMustBeFound()
        {
            var productFinder = new ProductFinder();
            var foundProducts = productFinder.Find("samsung", "galaxy", "s3");

            Assert.IsTrue(foundProducts.Any());
        }

        [TestMethod]
        public void IfSomeProductMatchesNoKeywordItMustNotBeFound()
        {
            var productFinder = new ProductFinder();
            var foundProducts = productFinder.Find(keywordForNoResults);

            Assert.IsFalse(foundProducts.Any());
        }

        [TestMethod]
        public void ThenResultsMustBeOrderedByRelevance()
        {
            var productFinder = new ProductFinder();
            var foundProducts = productFinder.Find("samsung", "galaxy", "s3");

            var firstProduct = foundProducts.First();
            var restProducts = foundProducts.Skip(1);

            Assert.IsTrue(firstProduct.Name.ToLowerInvariant().Contains("samsung")
                && firstProduct.Name.ToLowerInvariant().Contains("galaxy")
                && firstProduct.Name.ToLowerInvariant().Contains("s3")
                );

            Assert.IsFalse(
                restProducts.Any(p => 
                    p.Name.ToLowerInvariant().Contains("samsung")
                    && p.Name.ToLowerInvariant().Contains("galaxy")
                    && p.Name.ToLowerInvariant().Contains("s3")
                    )
                );
        }

        [TestMethod]
        public void IfNoProductFoundCrawlingMustBeInitiated()
        {
            var productCrawlerMock = new Mock<ICrawlForProducts>();

            var productFinder = new ProductFinder(productCrawlerMock.Object);
            var foundProducts = productFinder.Find(keywordForNoResults);

            productCrawlerMock.Verify(c => c.BeginCrawl(), Times.Once());
        }

        [TestMethod]
        public void IfAnyProductFoundCrawlingMustNotBeInitiated()
        {
            var productCrawlerMock = new Mock<ICrawlForProducts>();

            var productFinder = new ProductFinder(productCrawlerMock.Object);
            var foundProducts = productFinder.Find(keywordForSomeResults);

            productCrawlerMock.Verify(c => c.BeginCrawl(), Times.Never());
        }
    }
}
